package com.bcmusic.order.service.impl;

import com.alibaba.fastjson.JSON;
import com.bcmusic.authorization.feign.AuthorizationFeign;
import com.bcmusic.authorization.pojo.Authorization;
import com.bcmusic.music.feign.MusicFeign;
import com.bcmusic.music.feign.MusicPermissionFeign;
import com.bcmusic.music.pojo.Music;
import com.bcmusic.music.pojo.MusicPermission;
import com.bcmusic.order.dao.OrderCartMapper;
import com.bcmusic.order.dao.OrdersMapper;
import com.bcmusic.order.domain.cart.vo.OrderCartVO;
import com.bcmusic.order.domain.orders.dto.CreateTransferDTO;
import com.bcmusic.order.domain.orders.vo.CreateOrdersVO;
import com.bcmusic.order.domain.orders.vo.CreateTransferVO;
import com.bcmusic.order.pojo.OrderCart;
import com.bcmusic.order.pojo.Orders;
import com.bcmusic.order.service.OrdersService;
import com.bcmusic.pay.feign.WeixinPayFeign;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import entity.DateUtil;
import entity.IdWorker;
import entity.Result;
import entity.SmartBeanUtil;
import org.aspectj.weaver.SourceContextImpl;
import org.aspectj.weaver.ast.Or;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.test.annotation.Rollback;
import org.springframework.util.StringUtils;
import tk.mybatis.mapper.entity.Example;

import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/****
 * @Author:admin
 * @Description:Orders业务层接口实现类
 * @Date 2019/6/14 0:16
 *****/
@Service
public class OrdersServiceImpl implements OrdersService {

    @Autowired
    private OrdersMapper ordersMapper;
    @Autowired
    private IdWorker idWorker;
    @Autowired
    private OrderCartMapper orderCartMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private Environment env;
    @Autowired
    private MusicPermissionFeign musicPermissionFeign;
    @Autowired
    private AuthorizationFeign authorizationFeign;

    @Autowired
    private WeixinPayFeign weixinPayFeign;

    @Autowired
    private MusicFeign musicFeign;


    /**
     * Orders条件+分页查询
     *
     * @param orders 查询条件
     * @param page   页码
     * @param size   页大小
     * @return 分页结果
     */
    @Override
    public PageInfo<Orders> findPage(Orders orders, int page, int size) {
        //分页
        PageHelper.startPage(page, size);
        //搜索条件构建
        Example example = createExample(orders);
        //执行搜索
        return new PageInfo<Orders>(ordersMapper.selectByExample(example));
    }

    /**
     * Orders分页查询
     *
     * @param page
     * @param size
     * @return
     */
    @Override
    public PageInfo<Orders> findPage(int page, int size) {
        //静态分页
        PageHelper.startPage(page, size);
        //分页查询
        return new PageInfo<Orders>(ordersMapper.selectAll());
    }

    /**
     * Orders条件查询
     *
     * @param orders
     * @return
     */
    @Override
    public List<Orders> findList(Orders orders) {
        //构建查询条件
        Example example = createExample(orders);
        //根据构建的条件查询数据
        return ordersMapper.selectByExample(example);
    }


    /**
     * Orders构建查询对象
     *
     * @param orders
     * @return
     */
    /**
     * OrderDetail构建查询对象
     * @param orderDetail
     * @return
     */

    /**
     * Orders构建查询对象
     *
     * @param orders
     * @return
     */
    public Example createExample(Orders orders) {
        Example example = new Example(Orders.class);
        Example.Criteria criteria = example.createCriteria();
        if (orders != null) {
            // 音乐订单id。
            if (!StringUtils.isEmpty(orders.getOrderId())) {
                criteria.andEqualTo("orderId", orders.getOrderId());
            }
            // 被授权方编号。关联user表的user_number字段。
            if (!StringUtils.isEmpty(orders.getUserNumber())) {
                criteria.andEqualTo("userNumber", orders.getUserNumber());
            }
            // 支付方式。（暂定）00默认为MB支付，01为第三方支付。
            if (!StringUtils.isEmpty(orders.getPaymentMethod())) {
                criteria.andEqualTo("paymentMethod", orders.getPaymentMethod());
            }
            // 订单总额。订单总额 = 支付总额 + 优惠总额。
            if (!StringUtils.isEmpty(orders.getOrderAmount())) {
                criteria.andEqualTo("orderAmount", orders.getOrderAmount());
            }
            // 优惠总额。
            if (!StringUtils.isEmpty(orders.getDiscountAmount())) {
                criteria.andEqualTo("discountAmount", orders.getDiscountAmount());
            }
            // 支付总额。
            if (!StringUtils.isEmpty(orders.getPaymentAmount())) {
                criteria.andEqualTo("paymentAmount", orders.getPaymentAmount());
            }
            // 音乐订单MB积分。即被授权方完成该订单可获得的MB积分回馈。
            if (!StringUtils.isEmpty(orders.getOrderMbPoint())) {
                criteria.andEqualTo("orderMbPoint", orders.getOrderMbPoint());
            }
            // 音乐订单状态。0默认为待支付，1为已支付，2为已完成，-1为已取消，-2为已过期。被授权方支付后要确认到账才算完成该订单。订单超时未支付会过期。
            if (!StringUtils.isEmpty(orders.getValidStatus())) {
                criteria.andEqualTo("validStatus", orders.getValidStatus());
            }
            // 提交时间。默认为订单提交时间。
            if (!StringUtils.isEmpty(orders.getCreateTime())) {
                criteria.andEqualTo("createTime", orders.getCreateTime());
            }
            // 支付时间。即被授权方完成支付的时间。
            if (!StringUtils.isEmpty(orders.getPayTime())) {
                criteria.andEqualTo("payTime", orders.getPayTime());
            }
            // 完成时间。即确认支付的账款到账/取消订单/订单超时过期的时间。
            if (!StringUtils.isEmpty(orders.getFinishTime())) {
                criteria.andEqualTo("finishTime", orders.getFinishTime());
            }
        }
        return example;
    }


    /**
     * 将订单状态设置为未支付
     *
     * @param id
     */
    @Override
    public void unPay(Integer id) {
        Orders orders = new Orders();
        orders.setOrderId(id);
        orders.setValidStatus(-2);
        ordersMapper.updateByPrimaryKeySelective(orders);
    }

    /**
     * 修改Orders
     *
     * @param orders
     */
    @Override
    public void update(Orders orders) {
        ordersMapper.updateByPrimaryKey(orders);
    }

    /**
     * 增加Orders
     *
     * @param orders
     */
    @Override
    public void add(Orders orders) {
        ordersMapper.insert(orders);
    }

    /**
     * 根据ID查询Orders
     *
     * @param id
     * @return
     */
    @Override
    public Orders findById(Integer id) {
        return ordersMapper.selectByPrimaryKey(id);
    }

    /**
     * 查询Orders全部数据
     *
     * @return
     */
    @Override
    public List<Orders> findAll() {
        return ordersMapper.selectAll();
    }

    /**
     * 创建订单
     *
     * @param userNum
     * @param permissionIdList
     * @return
     */
    @Rollback
    @Override
    public CreateOrdersVO createOrder(String userNum, List<Integer> permissionIdList) {
        if (permissionIdList.size() == 0) {
            return null;
        }
        List<MusicPermission> data = musicPermissionFeign.getPermissionByIdList(permissionIdList).getData();
        //如果有无效的让用户刷新购物车重试
        for (int i = 0; i < data.size(); i++) {
            if (!data.get(i).getValidStatus().equals(1)) {
                return null;
            }
        }
        List<OrderCart> list = redisTemplate.boundHashOps("orderCart" + userNum).multiGet(permissionIdList);
        BigDecimal totalMoney = new BigDecimal("0.00");
        for (int i = 0; i < Objects.requireNonNull(list).size(); i++) {
            totalMoney = totalMoney.add(new BigDecimal(list.get(i).getTotalPrices()));
        }
        Long id = idWorker.nextId();

        //这里没更新时间。。。后面填坑
        CreateOrdersVO order = new CreateOrdersVO();
        order.setDiscountAmount("0");
        order.setPaymentAmount(totalMoney.toString());
        order.setOrderAmount(totalMoney.toString());
        order.setOrderId(id.toString());
        order.setUserNum(userNum);

        List<OrderCartVO> orderCartVOS = SmartBeanUtil.copyList(list, OrderCartVO.class);
        List<Integer> musicIdList = new ArrayList<>();
        for (OrderCartVO orderCartVO : orderCartVOS) {
            musicIdList.add(orderCartVO.getMusicId());
        }
        List<Music> musicByIdList = musicFeign.getMusicByIdList(musicIdList).getData();

        for (int i = 0; i < orderCartVOS.size(); i++) {
            Music music = musicByIdList.get(i);
            orderCartVOS.get(i).setSinger(music.getSinger());
            orderCartVOS.get(i).setLyricist(music.getLyricist());
            orderCartVOS.get(i).setComposer(music.getComposer());
            orderCartVOS.get(i).setMusicName(music.getMusicName());
            orderCartVOS.get(i).setUserNumber(music.getOwnerNumber());
        }

        order.setOrderCartList(orderCartVOS);

        //将购物车列表放入redis中，设置过期时间30分钟，如果用户没有提交订单就自动删除。。暂时找不到方法对里面每一个hash设置过期时间
        //防止其上次有没有支付的订单
        redisTemplate.boundHashOps("unSubmitCart").delete(userNum);
        //放到未提交订单列表中，不删除购物车
        redisTemplate.boundHashOps("unSubmitCart").put(userNum, permissionIdList);
        redisTemplate.boundHashOps("unSubmitOrders").put(id.toString(), order);
        System.out.println(id);
        return order;
    }

    @Rollback
    @Override
    public Map<String, String> submitOrders(String userNum, String orderId) {
        System.out.println(orderId);
        CreateOrdersVO ordersVO = (CreateOrdersVO) redisTemplate.boundHashOps("unSubmitOrders").get(orderId);
        //如果预提交的订单过期或者不是这个人的订单，返回失败
        if (ordersVO == null || !ordersVO.getUserNum().equals(userNum)) {
            return null;
        }
        Orders orders = new Orders();
        orders.setUserNumber(userNum);
        orders.setOrderAmount(ordersVO.getOrderAmount());
        orders.setDiscountAmount(ordersVO.getDiscountAmount());
        orders.setPaymentAmount(ordersVO.getPaymentAmount());

        ordersMapper.insertSelective(orders);
        //删除redis缓存的订单中的物品id
        List<Integer> permissionIdList = (List<Integer>) redisTemplate.boundHashOps("unSubmitCart").get(userNum);
        //将redis购物车中这些物品放入数据库中
        List<OrderCart> list = redisTemplate.boundHashOps("orderCart" + userNum).multiGet(permissionIdList);
        //这里不知道是不是selective //TODO 校验插入是否正确
        for (int i = 0; i < list.size(); i++) {
            list.get(i).setOrderCartId(orders.getOrderId());
        }
        //循环插入先，下个版本用xml改
        for (int i = 0; i < list.size(); i++) {
            orderCartMapper.insertSelective(list.get(i));
        }

        //删除reids中购物车对应的数据,一次性删除不知道为啥莫名其妙用不了
        for (int i = 0; i < permissionIdList.size(); i++) {
            redisTemplate.boundHashOps("orderCart" + userNum).delete(permissionIdList.get(i));
        }
        //订单放入redis中
        redisTemplate.boundHashOps("orders").put(orders.getOrderId(), orders);
        //订单放入延迟队列
        rabbitTemplate.convertAndSend(env.getProperty("mq.pay.queue.ordertimerdelay"), (Object) JSON.toJSONString(orders), new MessagePostProcessor() {
            @Override
            public Message postProcessMessage(Message message) throws AmqpException {
                //过期时间为0.5个小时
                message.getMessageProperties().setExpiration("1800000");
                return message;
            }
        });
        //redis 删除对应的购物车信息,一起删除莫名其妙用不了
        for (int i = 0; i < ordersVO.getOrderCartList().size(); i++) {
            redisTemplate.boundHashOps("orderCart" + userNum).delete(ordersVO.getOrderCartList().get(i).getPermissionId());
        }
        BigDecimal money = new BigDecimal(orders.getPaymentAmount());
        money = money.multiply(new BigDecimal(100));
        Map<String, String> aNative = weixinPayFeign.createNative(orders.getOrderId().toString(), money.toString()).getData();
        return aNative;
    }

    @Override
    public void pay(Integer orderId) {
        Orders orders = new Orders();
        orders.setOrderId(orderId);
        //等后面版权存储了才算已经完成，这里只算已支付;
        orders.setValidStatus(1);
    }

    @Override
    public void finishOrder(Integer orderId) {
        Orders order = new Orders();
        order.setOrderId(orderId);
        order.setValidStatus(2);
        ordersMapper.updateByPrimaryKeySelective(order);
    }

    /**
     * 这个接口涉及到多次跨微服务调用，时间可能会很久很久。。
     *
     * @param createTransferDTO
     * @param userNum
     * @return
     * @throws ParseException
     */
    @Override
    public CreateTransferVO createTransferOrder(CreateTransferDTO createTransferDTO, String userNum) throws ParseException {
        Integer permissionId = createTransferDTO.getPermissionId();
        MusicPermission permission = musicPermissionFeign.getPermissionById(permissionId).getData();
        if (permission == null) {
            return null;
        }
        Stack<String> allowTypes = toStack(permission.getAllowType());
        for (String type : createTransferDTO.getAllowType()) {
            if (!allowTypes.contains(type)) {
                return null;
            }
        }
        List<Authorization> authorizationList = authorizationFeign.getCurrentTransferById(permission.getMusicId()).getData();
        for (Authorization authorization : authorizationList) {
            Stack<String> strings = toStack(authorization.getAllowType());
            for (String type : createTransferDTO.getAllowType()) {
                if (strings.contains(type)) {
                    if (DateUtil.isIntersect(authorization.getAuthorizationStartTime(), authorization.getAuthorizationEndTime(), createTransferDTO.getAuthorizationStartTime(), createTransferDTO.getAuthorizationEndTime())) {
                        //已经有人买了这个时间段的
                        return null;
                    }
                }
            }
        }
        //TODO 在先前购买的队列进行判断

        Orders order = new Orders();
        order.setUserNumber(userNum);
        order.setValidStatus(0);

        BigDecimal total = new BigDecimal(permission.getPricePerDay());
        Integer length = createTransferDTO.getAllowType().length;
        Integer date = DateUtil.differentDaysByMillisecond(createTransferDTO.getAuthorizationStartTime(), createTransferDTO.getAuthorizationEndTime());
        total = total.multiply(new BigDecimal(length * date));
        if (total.divide(new BigDecimal(length)).compareTo(new BigDecimal(permission.getPerpetualPrice())) > 0) {
            total = new BigDecimal(permission.getPerpetualPrice());
            DateFormat dateFormat1 = new SimpleDateFormat("yyyy-MM-dd");
            Date newEndDay = dateFormat1.parse("2100-06-01");
            //设置为永久授权
            createTransferDTO.setAuthorizationEndTime(newEndDay);
        }
        order.setPaymentAmount(total.toString());
        order.setDiscountAmount("0");
        order.setOrderAmount(total.toString());
        order.setPaymentMethod(0);

        ordersMapper.insertSelective(order);

        OrderCart orderCart = new OrderCart();
        OrderCart copy = SmartBeanUtil.copy(createTransferDTO, OrderCart.class);
        copy.setType(2);
        copy.setTotalPrices(total.toString());
        copy.setUserNumber(userNum);
        orderCartMapper.insertSelective(copy);

        //订单放入redis中
        redisTemplate.boundHashOps("orders").put(order.getOrderId(), order);
        //订单放入延迟队列
        rabbitTemplate.convertAndSend(env.getProperty("mq.pay.queue.ordertimerdelay"), (Object) JSON.toJSONString(order), new MessagePostProcessor() {
            @Override
            public Message postProcessMessage(Message message) throws AmqpException {
                //过期时间为0.5个小时
                message.getMessageProperties().setExpiration("1800000");
                return message;
            }
        });
        String outtradeno = order.getOrderId().toString();
        String money = (new BigDecimal(order.getPaymentAmount()).multiply(new BigDecimal(100))).toString();
        String payUrl = (String) weixinPayFeign.createNative(outtradeno, money).getData().get("code_url");

        Music music = musicFeign.findById(permission.getMusicId()).getData();

        CreateTransferVO createTransferVO = SmartBeanUtil.copy(createTransferDTO, CreateTransferVO.class);
        SmartBeanUtil.copyProperties(order, createTransferVO);
        SmartBeanUtil.copyProperties(music, createTransferVO);
        createTransferVO.setPayUrl(payUrl);
        return createTransferVO;
    }


//    /**
//     * 创建订单,如果购物车时间过去了，就会自动设置成当前时间，从当前时间
//     * 开始收费
//     *
//     * @param list
//     * @return
//     */
//    @Rollback//失败全部回滚
//    @Override
//    public Orders CreateOrders(List<OrderCart> list, String userNum) {
//        Orders orders = new Orders();
//        orders.setOrderNumber(String.valueOf(idWorker.nextId()));
//        orders.setAuthorizedNumber(userNum);
//        //购物车中对应id，由于没有对应字段，只能放到redis中。
//        List<Integer> idList = new ArrayList<>();
//        //每件商品应该付的钱列表
//        Map<Integer, String> perPay = new HashMap<>();
//        //每件打折的钱
//        Map<Integer,String>perDis=new HashMap<>();
//        //四舍五入保留两位小数
//        DecimalFormat df = new DecimalFormat("0.00");
//        //计算总金额
//        BigDecimal orderAmount = new BigDecimal(0);
//        for (int i = 0; i < list.size(); i++) {
//            //如果起始时间是今天以前就把时间调成今天
//            if (list.get(i).getAuthorizationStartTime().compareTo(new Date()) == -1) {
//                list.get(i).setAuthorizationStartTime(new Date());
//            }
//            int intevalDay = DateUtil.getIntevalDay(list.get(i).getAuthorizationStartTime(), list.get(i).getAuthorizationEndTime());
//            //我只想写一个+=。。。。。。
//            //这个加有毒。。。
//            BigDecimal perAmount=new BigDecimal(list.get(0).getPricePerDay()).multiply(new BigDecimal(String.valueOf(intevalDay)));
//
//            orderAmount = orderAmount.add(perAmount);
//            //生成订单的同时将redis中的购物车数据添加到数据库中,方便后面生成订单详情
//            int id = list.get(i).getOrderCartId();
//            perPay.put(id,df.format(perAmount.multiply(new BigDecimal("0.95"))));
//            perDis.put(id,df.format(perAmount.multiply(new BigDecimal("0.05"))));
//            idList.add(id);
//        }
//
//
//        //设置总金额，优惠金额，应付金额，目前写死9.5折
//        orders.setOrderAmount(df.format(orderAmount));
//        orders.setPaymentAmount(df.format(orderAmount.multiply(new BigDecimal("0.95"))));
//        orders.setDiscountAmount(df.format(orderAmount.multiply(new BigDecimal("0.05"))));
//        orders.setCreateTime(new Date());
//        orders.setValidStatus(0);
//        //TODO 再校验一次合法性，，，，
//        ordersMapper.insertSelective(orders);
//        //将订单对应发布信息列表放入redis缓存，方便后面生成购物车
//        redisTemplate.boundHashOps(userNum +"_orderItems").put(orders.getOrderId(), idList);
//        //每件商品付的价钱,结构不对，后面改
//        redisTemplate.boundHashOps(orders.getOrderId()).put(orders.getOrderId()+"_perPay",perPay);
//        //每件商品折扣价钱
//        redisTemplate.boundHashOps(orders.getOrderId()).put(orders.getOrderId()+"_perDis",perDis);
//        //将订单放入redis，方便定时任务查询支付状态（如果是数据库太耗费性能）
//        redisTemplate.boundHashOps("Order").put(orders.getOrderId(), orders);
//
//        //放入延迟队列
//        rabbitTemplate.convertAndSend(env.getProperty("mq.pay.queue.ordertimerdelay"), (Object) JSON.toJSONString(orders), new MessagePostProcessor() {
//            @Override
//            public Message postProcessMessage(Message message) throws AmqpException {
//                //过期时间为0.5个小时
//                message.getMessageProperties().setExpiration("1800000");
//                return message;
//            }
//        });
//        return orders;
//    }

    public Stack<String> toStack(String s) {
        if (s == null) {
            return null;
        }
        StringBuilder stringBuilder = new StringBuilder(s);
        stringBuilder.delete(0, 1);
        stringBuilder.delete(stringBuilder.length() - 1, stringBuilder.length());
        String[] s1 = stringBuilder.toString().split(",");

        if (s1.length == 0 || s1[0].equals("")) {
            return null;
        }
        Stack<String> stack = new Stack<>();
        for (int i = 0; i < s1.length; i++) {
            stack.add(s1[i]);
        }
        return stack;
    }

    public static void main(String[] args) throws ParseException {
        DateFormat dateFormat1 = new SimpleDateFormat("yyyy-MM-dd");
        Date myDate1 = dateFormat1.parse("2009-06-01");

    }
}
